1//////////////////////////////////////////////////////////////////////
2// LibFile: masks3d.scad
3// This file defines 3D masks for applying chamfers, roundovers, and teardrop roundovers to straight edges and circular
4// edges in three dimensions.
5// Includes:
6// include <BOSL2/std.scad>
7// FileGroup: Basic Modeling
8// FileSummary: 3D masks for rounding or chamfering edges and corners.
9// FileFootnotes: STD=Included in std.scad
10//////////////////////////////////////////////////////////////////////
11
12
13// Section: Chamfer Masks
14
15
16// Module: chamfer_edge_mask()
17// Synopsis: Creates a shape to chamfer a 90° edge.
18// SynTags: Geom
19// Topics: Masking, Chamfers, Shapes (3D)
20// See Also: chamfer_corner_mask(), chamfer_cylinder_mask(), chamfer_edge_mask(), default_tag(), diff()
21// Usage:
22// chamfer_edge_mask(l|h=|length=|height=, chamfer, [excess]) [ATTACHMENTS];
23// Description:
24// Creates a shape that can be used to chamfer a 90° edge.
25// Difference it from the object to be chamfered. The center of
26// the mask object should align exactly with the edge to be chamfered.
27// Arguments:
28// l/h/length/height = Length of mask.
29// chamfer = Size of chamfer.
30// excess = The extra amount to add to the length of the mask so that it differences away from other shapes cleanly. Default: `0.1`
31// ---
32// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
33// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
34// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
35// Side Effects:
36// Tags the children with "remove" (and hence sets `$tag`) if no tag is already set.
37// Example:
38// chamfer_edge_mask(l=50, chamfer=10);
39// Example:
40// difference() {
41// cube(50, anchor=BOTTOM+FRONT);
42// #chamfer_edge_mask(l=50, chamfer=10, orient=RIGHT);
43// }
44// Example: Masking by Attachment
45// diff()
46// cube(50, center=true) {
47// edge_mask(TOP+RIGHT)
48// #chamfer_edge_mask(l=50, chamfer=10);
49// }
50function chamfer_edge_mask(l, chamfer=1, excess=0.1, h, length, height, anchor=CENTER, spin=0, orient=UP) = no_function("chamfer_edge_mask");
51module chamfer_edge_mask(l, chamfer=1, excess=0.1, h, length, height, anchor=CENTER, spin=0, orient=UP) {
52 l = one_defined([l, h, height, length], "l,h,height,length");
53 default_tag("remove") {
54 attachable(anchor,spin,orient, size=[chamfer*2, chamfer*2, l]) {
55 cylinder(r=chamfer, h=l+excess, center=true, $fn=4);
56 children();
57 }
58 }
59}
60
61
62// Module: chamfer_corner_mask()
63// Synopsis: Creates a shape to chamfer a 90° corner.
64// SynTags: Geom
65// Topics: Masking, Chamfers, Shapes (3D)
66// See Also: chamfer_corner_mask(), chamfer_cylinder_mask(), chamfer_edge_mask(), default_tag(), diff()
67// Usage:
68// chamfer_corner_mask(chamfer) [ATTACHMENTS];
69// Description:
70// Creates a shape that can be used to chamfer a 90° corner.
71// Difference it from the object to be chamfered. The center of
72// the mask object should align exactly with the corner to be chamfered.
73// Arguments:
74// chamfer = Size of chamfer.
75// ---
76// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
77// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
78// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
79// Side Effects:
80// Tags the children with "remove" (and hence sets `$tag`) if no tag is already set.
81// Example:
82// chamfer_corner_mask(chamfer=10);
83// Example:
84// difference() {
85// cuboid(50, chamfer=10, trimcorners=false);
86// move(25*[1,-1,1]) #chamfer_corner_mask(chamfer=10);
87// }
88// Example: Masking by Attachment
89// diff()
90// cuboid(100, chamfer=20, trimcorners=false) {
91// corner_mask(TOP+FWD+RIGHT)
92// chamfer_corner_mask(chamfer=20);
93// }
94// Example: Anchors
95// chamfer_corner_mask(chamfer=20)
96// show_anchors();
97function chamfer_corner_mask(chamfer=1, anchor=CENTER, spin=0, orient=UP) = no_function("chamfer_corner_mask");
98module chamfer_corner_mask(chamfer=1, anchor=CENTER, spin=0, orient=UP) {
99 default_tag("remove") {
100 octahedron(chamfer*4, anchor=anchor, spin=spin, orient=orient) children();
101 }
102}
103
104
105// Module: chamfer_cylinder_mask()
106// Synopsis: Creates a shape to chamfer the end of a cylinder.
107// SynTags: Geom
108// Topics: Masking, Chamfers, Cylinders
109// See Also: chamfer_corner_mask(), chamfer_cylinder_mask(), chamfer_edge_mask(), default_tag(), diff()
110// Usage:
111// chamfer_cylinder_mask(r|d=, chamfer, [ang], [from_end]) [ATTACHMENTS];
112// Description:
113// Create a mask that can be used to bevel/chamfer the end of a cylindrical region.
114// Difference it from the end of the region to be chamfered. The center of the mask
115// object should align exactly with the center of the end of the cylindrical region
116// to be chamfered.
117// Arguments:
118// r = Radius of cylinder to chamfer.
119// chamfer = Size of the edge chamfered, inset from edge.
120// ---
121// d = Diameter of cylinder to chamfer. Use instead of r.
122// ang = Angle of chamfer in degrees from the horizontal. (Default: 45)
123// from_end = If true, chamfer size is measured from end of cylinder. If false, chamfer is measured outset from the radius of the cylinder. (Default: false)
124// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
125// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
126// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
127// Side Effects:
128// Tags the children with "remove" (and hence sets `$tag`) if no tag is already set.
129// Example:
130// difference() {
131// cylinder(r=50, h=100, center=true);
132// up(50) #chamfer_cylinder_mask(r=50, chamfer=10);
133// }
134// Example:
135// difference() {
136// cylinder(r=50, h=100, center=true);
137// up(50) chamfer_cylinder_mask(r=50, chamfer=10);
138// }
139// Example: Changing the chamfer angle
140// difference() {
141// cylinder(r=50, h=100, center=true);
142// up(50) #chamfer_cylinder_mask(r=50, chamfer=10, ang=70);
143// }
144// Example:
145// difference() {
146// cylinder(r=50, h=100, center=true);
147// up(50) chamfer_cylinder_mask(r=50, chamfer=10, ang=70);
148// }
149// Example: Masking by Attachment
150// diff()
151// cyl(d=100,h=40)
152// attach([TOP,BOT])
153// tag("remove")chamfer_cylinder_mask(d=100, chamfer=10);
154function chamfer_cylinder_mask(r, chamfer, d, ang=45, from_end=false, anchor=CENTER, spin=0, orient=UP) = no_function("chamfer_cylinder_mask");
155module chamfer_cylinder_mask(r, chamfer, d, ang=45, from_end=false, anchor=CENTER, spin=0, orient=UP)
156{
157 r = get_radius(r=r, d=d, dflt=1);
158 dummy = assert(all_nonnegative([chamfer]), "Chamfer must be a nonnegative number");
159 ch = from_end? chamfer : opp_ang_to_adj(chamfer,90-ang);
160 default_tag("remove"){
161 attachable(anchor,spin,orient, r=r, l=ch*2) {
162 difference() {
163 cyl(r=r+chamfer, l=ch*2, anchor=CENTER);
164 cyl(r=r, l=ch*3, chamfer=chamfer, chamfang=ang, from_end=from_end, anchor=TOP);
165 }
166 children();
167 }
168 }
169}
170
171
172
173// Section: Rounding Masks
174
175// Module: rounding_edge_mask()
176// Synopsis: Creates a shape to round a 90° edge.
177// SynTags: Geom
178// Topics: Masks, Rounding, Shapes (3D)
179// See Also: rounding_angled_edge_mask(), rounding_corner_mask(), rounding_angled_corner_mask(), default_tag(), diff()
180// Usage:
181// rounding_edge_mask(l|h=|length=|height=, r|d=, [excess=]) [ATTACHMENTS];
182// rounding_edge_mask(l|h=|length=|height=, r1=|d1=, r2=|d2=, [excess=]) [ATTACHMENTS];
183// Description:
184// Creates a shape that can be used to round a vertical 90° edge.
185// Difference it from the object to be rounded. The center of the mask
186// object should align exactly with the edge to be rounded.
187// Arguments:
188// l/h/length/height = Length of mask.
189// r = Radius of the rounding.
190// ---
191// r1 = Bottom radius of rounding.
192// r2 = Top radius of rounding.
193// d = Diameter of the rounding.
194// d1 = Bottom diameter of rounding.
195// d2 = Top diameter of rounding.
196// excess = Extra size for the mask. Defaults: 0.1
197// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
198// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
199// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
200// Side Effects:
201// Tags the children with "remove" (and hence sets `$tag`) if no tag is already set.
202// Example(VPD=200,VPR=[55,0,120]):
203// rounding_edge_mask(l=50, r1=10, r2=25);
204// Example:
205// difference() {
206// cube(size=100, center=false);
207// #rounding_edge_mask(l=100, r=25, orient=UP, anchor=BOTTOM);
208// }
209// Example: Varying Rounding Radius
210// difference() {
211// cube(size=50, center=false);
212// #rounding_edge_mask(l=50, r1=25, r2=10, orient=UP, anchor=BOTTOM);
213// }
214// Example: Masking by Attachment
215// diff()
216// cube(100, center=true)
217// edge_mask(FRONT+RIGHT)
218// #rounding_edge_mask(l=$parent_size.z+0.01, r=25);
219// Example: Multiple Masking by Attachment
220// diff()
221// cube([80,90,100], center=true) {
222// let(p = $parent_size*1.01) {
223// edge_mask(TOP)
224// rounding_edge_mask(l=p.z, r=25);
225// }
226// }
227function rounding_edge_mask(l, r, r1, r2, d, d1, d2, excess=0.1, anchor=CENTER, spin=0, orient=UP, h,height,length) = no_function("rounding_edge_mask");
228module rounding_edge_mask(l, r, r1, r2, d, d1, d2, excess=0.1, anchor=CENTER, spin=0, orient=UP, h,height,length)
229{
230 l = one_defined([l, h, height, length], "l,h,height,length");
231 r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1);
232 r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1);
233 sides = quantup(segs(max(r1,r2)),4);
234 default_tag("remove") {
235 attachable(anchor,spin,orient, size=[2*r1,2*r1,l], size2=[2*r2,2*r2]) {
236 if (r1<r2) {
237 zflip() {
238 linear_extrude(height=l, convexity=4, center=true, scale=r1/r2) {
239 difference() {
240 translate(-excess*[1,1]) square(r2+excess);
241 translate([r2,r2]) circle(r=r2, $fn=sides);
242 }
243 }
244 }
245 } else {
246 linear_extrude(height=l, convexity=4, center=true, scale=r2/r1) {
247 difference() {
248 translate(-excess*[1,1]) square(r1+excess);
249 translate([r1,r1]) circle(r=r1, $fn=sides);
250 }
251 }
252 }
253 children();
254 }
255 }
256}
257
258
259// Module: rounding_corner_mask()
260// Synopsis: Creates a shape to round 90° corners.
261// SynTags: Geom
262// Topics: Masking, Rounding, Shapes (3D)
263// See Also: rounding_angled_corner_mask(), rounding_edge_mask(), rounding_angled_edge_mask(), default_tag(), diff()
264// Usage:
265// rounding_corner_mask(r|d, [excess=], [style=]) [ATTACHMENTS];
266// Description:
267// Creates a shape that you can use to round 90° corners.
268// Difference it from the object to be rounded. The center of the mask
269// object should align exactly with the corner to be rounded.
270// Arguments:
271// r = Radius of corner rounding.
272// ---
273// d = Diameter of corner rounding.
274// excess = Extra size for the mask. Defaults: 0.1
275// style = The style of the sphere cutout's construction. One of "orig", "aligned", "stagger", "octa", or "icosa". Default: "octa"
276// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
277// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
278// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
279// Side Effects:
280// Tags the children with "remove" (and hence sets `$tag`) if no tag is already set.
281// Example:
282// rounding_corner_mask(r=20.0);
283// Example:
284// difference() {
285// cube(size=[50, 60, 70], center=true);
286// translate([-25, -30, 35])
287// #rounding_corner_mask(r=20, spin=90, orient=DOWN);
288// translate([25, -30, 35])
289// #rounding_corner_mask(r=20, orient=DOWN);
290// translate([25, -30, -35])
291// #rounding_corner_mask(r=20, spin=90);
292// }
293// Example: Masking by Attachment
294// diff()
295// cube(size=[50, 60, 70]) {
296// corner_mask(TOP)
297// #rounding_corner_mask(r=20);
298// }
299function rounding_corner_mask(r, d, style="octa", excess=0.1, anchor=CENTER, spin=0, orient=UP) = no_function("rounding_corner_mask");
300module rounding_corner_mask(r, d, style="octa", excess=0.1, anchor=CENTER, spin=0, orient=UP)
301{
302 r = get_radius(r=r, d=d, dflt=1);
303 default_tag("remove") {
304 attachable(anchor,spin,orient, size=[2,2,2]*r) {
305 difference() {
306 translate(-excess*[1,1,1])
307 cube(size=r+excess, center=false);
308 translate([r,r,r])
309 spheroid(r=r, style=style);
310 }
311 children();
312 }
313 }
314}
315
316
317// Module: rounding_angled_edge_mask()
318// Synopsis: Creates a shape to round edges of any angle.
319// SynTags: Geom
320// Topics: Masks, Rounding
321// See Also: rounding_angled_corner_mask(), rounding_edge_mask(), rounding_corner_mask(), default_tag(), diff()
322// Usage:
323// rounding_angled_edge_mask(h|l=|length=|height=, r|d=, [ang=]) [ATTACHMENTS];
324// rounding_angled_edge_mask(h|l=|length=|height=, r1=|d1=, r2=|d2=, [ang=]) [ATTACHMENTS];
325// Description:
326// Creates a vertical mask that can be used to round the edge where two face meet, at any arbitrary
327// angle. Difference it from the object to be rounded. The center of the mask should align exactly
328// with the edge to be rounded.
329// Arguments:
330// h/l/height/length = Height of vertical mask.
331// r = Radius of the rounding.
332// ---
333// r1 = Bottom radius of rounding.
334// r2 = Top radius of rounding.
335// d = Diameter of the rounding.
336// d1 = Bottom diameter of rounding.
337// d2 = Top diameter of rounding.
338// ang = Angle that the planes meet at. Default: 90
339// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
340// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
341// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
342// Side Effects:
343// Tags the children with "remove" (and hence sets `$tag`) if no tag is already set.
344// Example:
345// difference() {
346// pie_slice(ang=70, h=50, d=100, center=true);
347// #rounding_angled_edge_mask(h=51, r=20.0, ang=70, $fn=32);
348// }
349// Example: Varying Rounding Radius
350// difference() {
351// pie_slice(ang=70, h=50, d=100, center=true);
352// #rounding_angled_edge_mask(h=51, r1=10, r2=25, ang=70, $fn=32);
353// }
354function rounding_angled_edge_mask(h, r, r1, r2, d, d1, d2, ang=90, anchor=CENTER, spin=0, orient=UP,l,height,length) = no_function("rounding_angled_edge_mask");
355module rounding_angled_edge_mask(h, r, r1, r2, d, d1, d2, ang=90, anchor=CENTER, spin=0, orient=UP,l,height,length)
356{
357 function _mask_shape(r) = [
358 for (i = [0:1:n]) let (a=90+ang+i*sweep/n) [r*cos(a)+x, r*sin(a)+r],
359 for (i = [0:1:n]) let (a=90+i*sweep/n) [r*cos(a)+x, r*sin(a)-r],
360 [min(-1, r*cos(270-ang)+x-1), r*sin(270-ang)-r],
361 [min(-1, r*cos(90+ang)+x-1), r*sin(90+ang)+r],
362 ];
363 h = one_defined([l, h, height, length], "l,h,height,length");
364 sweep = 180-ang;
365 r1 = get_radius(r1=r1, r=r, d1=d1, d=d, dflt=1);
366 r2 = get_radius(r1=r2, r=r, d1=d2, d=d, dflt=1);
367 n = ceil(segs(max(r1,r2))*sweep/360);
368 x = sin(90-(ang/2))/sin(ang/2) * (r1<r2? r2 : r1);
369 if(r1<r2) {
370 default_tag("remove") {
371 attachable(anchor,spin,orient, size=[2*x*r1/r2,2*r1,h], size2=[2*x,2*r2]) {
372 zflip() {
373 linear_extrude(height=h, convexity=4, center=true, scale=r1/r2) {
374 polygon(_mask_shape(r2));
375 }
376 }
377 children();
378 }
379 }
380 } else {
381 default_tag("remove") {
382 attachable(anchor,spin,orient, size=[2*x,2*r1,h], size2=[2*x*r2/r1,2*r2]) {
383 linear_extrude(height=h, convexity=4, center=true, scale=r2/r1) {
384 polygon(_mask_shape(r1));
385 }
386 children();
387 }
388 }
389 }
390}
391
392
393// Module: rounding_angled_corner_mask()
394// Synopsis: Creates a shape to round the corner of an arbitrary angle.
395// SynTags: Geom
396// Topics: Masks, Rounding, Shapes (3D)
397// See Also: rounding_angled_edge_mask(), rounding_corner_mask(), rounding_edge_mask(), default_tag(), diff()
398// Usage:
399// rounding_angled_corner_mask(r|d=, [ang]) [ATTACHMENTS];
400// Description:
401// Creates a shape that can be used to round the corner of an angle.
402// Difference it from the object to be rounded. The center of the mask
403// object should align exactly with the point of the corner to be rounded.
404// Arguments:
405// r = Radius of the rounding.
406// ---
407// d = Diameter of the rounding.
408// ang = Angle between planes that you need to round the corner of. Default: 90
409// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
410// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
411// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
412// Side Effects:
413// Tags the children with "remove" (and hence sets `$tag`) if no tag is already set.
414// Example(Med):
415// ang=60;
416// difference() {
417// pie_slice(ang=ang, h=50, r=200, center=true);
418// up(50/2) #rounding_angled_corner_mask(r=20, ang=ang);
419// }
420function rounding_angled_corner_mask(r, ang=90, d, anchor=CENTER, spin=0, orient=UP) = no_function("rounding_angled_corner_mask");
421module rounding_angled_corner_mask(r, ang=90, d, anchor=CENTER, spin=0, orient=UP)
422{
423 r = get_radius(r=r, d=d, dflt=1);
424 dx = r / tan(ang/2);
425 dx2 = dx / cos(ang/2) + 1;
426 fn = quantup(segs(r), 4);
427 default_tag("remove") {
428 attachable(anchor,spin,orient, d=dx2, l=2*r) {
429 difference() {
430 down(r) cylinder(r=dx2, h=r+1, center=false);
431 yflip_copy() {
432 translate([dx, r, -r]) {
433 hull() {
434 sphere(r=r, $fn=fn);
435 down(r*3) sphere(r=r, $fn=fn);
436 zrot_copies([0,ang]) {
437 right(r*3) sphere(r=r, $fn=fn);
438 }
439 }
440 }
441 }
442 }
443 children();
444 }
445 }
446}
447
448
449// Module: rounding_cylinder_mask()
450// Synopsis: Creates a shape to round the end of a cylinder.
451// SynTags: Geom
452// Topics: Masking, Rounding, Cylinders
453// See Also: rounding_hole_mask(), rounding_angled_edge_mask(), rounding_corner_mask(), rounding_angled_corner_mask(), default_tag(), diff()
454// Usage:
455// rounding_cylinder_mask(r|d=, rounding);
456// Description:
457// Create a mask that can be used to round the end of a cylinder.
458// Difference it from the cylinder to be rounded. The center of the
459// mask object should align exactly with the center of the end of the
460// cylinder to be rounded.
461// Arguments:
462// r = Radius of cylinder.
463// rounding = Radius of the edge rounding.
464// ---
465// d = Diameter of cylinder.
466// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
467// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
468// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
469// Side Effects:
470// Tags the children with "remove" (and hence sets `$tag`) if no tag is already set.
471// Example:
472// difference() {
473// cylinder(r=50, h=50, center=false);
474// up(50) #rounding_cylinder_mask(r=50, rounding=10);
475// }
476// Example:
477// difference() {
478// cylinder(r=50, h=50, center=false);
479// up(50) rounding_cylinder_mask(r=50, rounding=10);
480// }
481// Example: Masking by Attachment
482// diff()
483// cyl(h=30, d=30) {
484// attach(TOP)
485// #tag("remove")
486// rounding_cylinder_mask(d=30, rounding=5);
487// }
488function rounding_cylinder_mask(r, rounding, d, anchor, spin, orient) = no_function("rounding_cylinder_mask");
489module rounding_cylinder_mask(r, rounding, d, anchor=CENTER, spin=0, orient=UP)
490{
491 r = get_radius(r=r, d=d, dflt=1);
492 default_tag("remove") {
493 attachable(anchor,spin,orient, r=r+rounding, l=rounding*2) {
494 difference() {
495 cyl(r=r+rounding, l=rounding*2, anchor=CENTER);
496 cyl(r=r, l=rounding*3, rounding=rounding, anchor=TOP);
497 }
498 children();
499 }
500 }
501}
502
503
504
505// Module: rounding_hole_mask()
506// Synopsis: Creates a shape to round the edge of a round hole.
507// SynTags: Geom
508// Topics: Masking, Rounding
509// See Also: rounding_cylinder_mask(), rounding_hole_mask(), rounding_angled_edge_mask(), rounding_corner_mask(), rounding_angled_corner_mask(), default_tag(), diff()
510// Usage:
511// rounding_hole_mask(r|d, rounding, [excess]) [ATTACHMENTS];
512// Description:
513// Create a mask that can be used to round the edge of a circular hole.
514// Difference it from the hole to be rounded. The center of the
515// mask object should align exactly with the center of the end of the
516// hole to be rounded.
517// Arguments:
518// r = Radius of hole.
519// rounding = Radius of the rounding.
520// excess = The extra thickness of the mask. Default: `0.1`.
521// ---
522// d = Diameter of hole to rounding.
523// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
524// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
525// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
526// Side Effects:
527// Tags the children with "remove" (and hence sets `$tag`) if no tag is already set.
528// Example:
529// rounding_hole_mask(r=40, rounding=20, $fa=2, $fs=2);
530// Example(Med):
531// difference() {
532// cube([150,150,100], center=true);
533// cylinder(r=50, h=100.1, center=true);
534// up(50) #rounding_hole_mask(r=50, rounding=10);
535// }
536// Example(Med):
537// difference() {
538// cube([150,150,100], center=true);
539// cylinder(r=50, h=100.1, center=true);
540// up(50) rounding_hole_mask(r=50, rounding=10);
541// }
542function rounding_hole_mask(r, rounding, excess=0.1, d, anchor=CENTER, spin=0, orient=UP) = no_function("rounding_hole_mask");
543module rounding_hole_mask(r, rounding, excess=0.1, d, anchor=CENTER, spin=0, orient=UP)
544{
545 r = get_radius(r=r, d=d, dflt=1);
546 default_tag("remove") {
547 attachable(anchor,spin,orient, r=r+rounding, l=2*rounding) {
548 rotate_extrude(convexity=4) {
549 difference() {
550 right(r-excess) fwd(rounding) square(rounding+excess, center=false);
551 right(r+rounding) fwd(rounding) circle(r=rounding);
552 }
553 }
554 children();
555 }
556 }
557}
558
559
560// Section: Teardrop Masking
561
562// Module: teardrop_edge_mask()
563// Synopsis: Creates a shape to round a 90° edge but limit the angle of overhang.
564// SynTags: Geom
565// Topics: Masking, Rounding, Shapes (3D), FDM Optimized
566// See Also: teardrop_corner_mask(), teardrop_edge_mask(), default_tag(), diff()
567// Usage:
568// teardrop_edge_mask(l|h=|length=|height=, r|d=, [angle], [excess], [anchor], [spin], [orient]) [ATTACHMENTS];
569// Description:
570// Makes an apropriate 3D edge rounding mask that keeps within `angle` degrees of vertical.
571// Arguments:
572// l/h/length/height = length of mask
573// r = Radius of the mask rounding.
574// angle = Maximum angle from vertical. Default: 45
575// excess = Excess mask size. Default: 0.1
576// ---
577// d = Diameter of the mask rounding.
578// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
579// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
580// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
581// Side Effects:
582// Tags the children with "remove" (and hence sets `$tag`) if no tag is already set.
583// Example(VPD=50,VPR=[55,0,120]):
584// teardrop_edge_mask(l=20, r=10, angle=40);
585// Example(VPD=300,VPR=[75,0,25]):
586// diff()
587// cuboid([50,60,70],rounding=10,edges="Z",anchor=CENTER) {
588// edge_mask(BOT)
589// teardrop_edge_mask(l=max($parent_size)+1, r=10, angle=40);
590// corner_mask(BOT)
591// teardrop_corner_mask(r=10, angle=40);
592// }
593function teardrop_edge_mask(l, r, angle=45, excess=0.1, d, anchor, spin, orient,h,height,length) = no_function("teardrop_edge_mask");
594module teardrop_edge_mask(l, r, angle=45, excess=0.1, d, anchor=CTR, spin=0, orient=UP,h,height,length)
595{
596 l = one_defined([l, h, height, length], "l,h,height,length");
597 check =
598 assert(is_num(l) && l>0, "Length of mask must be positive")
599 assert(is_num(angle) && angle>0 && angle<90, "Angle must be a number between 0 and 90")
600 assert(is_num(excess));
601 r = get_radius(r=r, d=d, dflt=1);
602 path = mask2d_teardrop(r=r, angle=angle, excess=excess);
603 default_tag("remove") {
604 linear_sweep(path, height=l, center=true, atype="bbox", anchor=anchor, spin=spin, orient=orient) children();
605 }
606}
607
608
609// Module: teardrop_corner_mask()
610// Synopsis: Creates a shape to round a 90° corner but limit the angle of overhang.
611// SynTags: Geom
612// Topics: Masking, Rounding, Shapes (3D), FDM Optimized
613// See Also: teardrop_corner_mask(), teardrop_edge_mask(), default_tag(), diff()
614// Usage:
615// teardrop_corner_mask(r|d=, [angle], [excess], [anchor], [spin], [orient]) [ATTACHMENTS];
616// Description:
617// Makes an apropriate 3D corner rounding mask that keeps within `angle` degrees of vertical.
618// Arguments:
619// r = Radius of the mask rounding.
620// angle = Maximum angle from vertical. Default: 45
621// excess = Excess mask size. Default: 0.1
622// ---
623// d = Diameter of the mask rounding.
624// anchor = Translate so anchor point is at origin (0,0,0). See [anchor](attachments.scad#subsection-anchor). Default: `CENTER`
625// spin = Rotate this many degrees around the Z axis after anchor. See [spin](attachments.scad#subsection-spin). Default: `0`
626// orient = Vector to rotate top towards, after spin. See [orient](attachments.scad#subsection-orient). Default: `UP`
627// Side Effects:
628// Tags the children with "remove" (and hence sets `$tag`) if no tag is already set.
629// Example:
630// teardrop_corner_mask(r=20, angle=40);
631// Example:
632// diff()
633// cuboid([50,60,70],rounding=10,edges="Z",anchor=CENTER) {
634// edge_profile(BOT)
635// mask2d_teardrop(r=10, angle=40);
636// corner_mask(BOT)
637// teardrop_corner_mask(r=10, angle=40);
638// }
639function teardrop_corner_mask(r, angle=45, excess=0.1, d, anchor, spin, orient) = no_function("teardrop_corner_mask");
640module teardrop_corner_mask(r, angle=45, excess=0.1, d, anchor=CTR, spin=0, orient=UP)
641{
642 assert(is_num(angle));
643 assert(is_num(excess));
644 assert(angle>0 && angle<90);
645 r = get_radius(r=r, d=d, dflt=1);
646 size = (r+excess) * [1,1,1];
647 midpt = (r-excess)/2 * [1,1,1];
648 default_tag("remove") {
649 attachable(anchor,spin,orient, size=size, offset=midpt) {
650 difference() {
651 translate(-[1,1,1]*excess) cube(r+excess, center=false);
652 translate([1,1,1]*r) onion(r=r, ang=angle, orient=DOWN);
653 }
654 children();
655 }
656 }
657}
658
659
660
661// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap